package com.novel.crawl.common.exception;

import com.mongodb.MongoException;
import com.novel.crawl.common.util.Rest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

/**
 * 全局异常处理
 *
 * @author 奔波儿灞
 * @since 1.0
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 自定义，服务异常
     *
     * @param e ServiceException
     * @return Rest
     */
    @ExceptionHandler(ServiceException.class)
    public Rest<?> serviceExceptionHandler(ServiceException e) {
        LOG.warn("ServiceException => ", e);
        return Rest.fail(e.getCode(), e.getMessage());
    }

    /**
     * 404，请求不存在
     *
     * @param e NoHandlerFoundException
     * @return Rest
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public Rest<?> noHandlerFoundExceptionHandler(NoHandlerFoundException e) {
        return Rest.fail(HttpStatus.NOT_FOUND, e.getMessage());
    }

    /**
     * 400，参数格式不正确
     *
     * @param e HttpMessageNotReadableException
     * @return Rest
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public Rest<?> httpMessageNotReadableExceptionHandler(HttpMessageNotReadableException e) {
        LOG.warn("HttpMessageNotReadableException => ", e);
        return Rest.fail(HttpStatus.BAD_REQUEST, e.getMessage());
    }

    /**
     * 400，参数校验不合法
     *
     * @param e MethodArgumentNotValidException
     * @return Rest
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Rest<?> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        LOG.warn("MethodArgumentNotValidException => ", e);
        // 拿到一个错误参数就提示
        FieldError fieldError = e.getBindingResult().getFieldError();
        return Rest.fail(HttpStatus.BAD_REQUEST, String.format("字段[%s]: %s", fieldError.getField(), fieldError.getDefaultMessage()));

    }

    /**
     * 405，请求方法不支持
     *
     * @param e HttpRequestMethodNotSupportedException
     * @return Rest
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Rest<?> httpRequestMethodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException e) {
        LOG.warn("HttpRequestMethodNotSupportedException => ", e);
        return Rest.fail(HttpStatus.METHOD_NOT_ALLOWED, e.getMessage());

    }

    /**
     * 500，mongo数据库异常
     *
     * @param e MongoException
     * @return Rest
     */
    @ExceptionHandler(MongoException.class)
    public Rest<?> mongoExceptionHandler(MongoException e) {
        LOG.warn("MongoException => ", e);
        return Rest.fail(HttpStatus.INTERNAL_SERVER_ERROR, "数据库异常，请稍后再试");
    }

    /**
     * 500，数据库连接异常
     *
     * @param e DataAccessResourceFailureException
     * @return Rest
     */
    @ExceptionHandler(DataAccessResourceFailureException.class)
    public Rest<?> dataAccessResourceFailureExceptionHandler(DataAccessResourceFailureException e) {
        LOG.warn("DataAccessResourceFailureException => ", e);
        return Rest.fail(HttpStatus.INTERNAL_SERVER_ERROR, "数据库异常，请稍后再试");
    }

    /**
     * 500，系统异常
     *
     * @param e Exception
     * @return Rest
     */
    @ExceptionHandler(Exception.class)
    public Rest<?> exceptionHandler(Exception e) {
        LOG.warn("Exception => ", e);
        return Rest.fail(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage());
    }

}
